package com.chalk.common.util;

import com.chalk.common.constant.CommonConstants;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;

/**
 * @author xiaoqiang
 * @Description 拼装SQL工具类
 * @date 2019/3/21 18:27
 */
public class AssembleSqlUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(AssembleSqlUtil.class);

    private static final String INSERT = "insert into";

    private static final String UPDATE = "update";

    private static final String SET = "set";

    private static final String WHERE = "where";

    private static final String TABLE_PREFIX = "t_";

    private static final String LEFT_BRACKET = "(";

    private static final String RIGHT_BRACKET = ")";

    private static final String VALUES = "values";

    private static final String COMMA = ",";

    private static final String EQUAL_SIGN = "=";

    private static final String SINGLE_QUOTES = "'";

    private static final String SPACE = " ";

    private static final String ID = "id";

    private static final String USERID = "userId";

    private static final String USER_ID = "user_id";

    private static final String AND = "and";

    private static final String SUFFIX = "";

    /**
     * 插入SQL
     *
     * @param obj 插入对象
     * @return
     */
    public static String insertSQL(Object obj) {
        /* SQL */
        StringBuffer sql = null;
        StringBuffer columns = new StringBuffer();
        StringBuffer values = new StringBuffer();
        /* 得到类对象 */
        Class<? extends Object> objClass = obj.getClass();
        /* 获取表名 */
        String tableName = classNameToTableName(objClass.getSimpleName(), TABLE_PREFIX, SUFFIX);
        /* 得到类中所有属性集合 */
        Field[] fields = objClass.getDeclaredFields();
        Arrays.asList(fields).forEach(field -> {
            /* 设置此属性可访问 */
            field.setAccessible(true);
            /* 属性名 */
            String propertyName = field.getName();
            try {
                /* 属性值 */
                Object propertyValue = field.get(obj);
                if (propertyValue != null && StringUtils.isNoneBlank(propertyValue.toString())) {
                    columns.append(javaPropertyToColumnName(propertyName)).append(COMMA);
                    if (field.getType() == String.class) {
                        values.append(SINGLE_QUOTES).append(propertyValue).append(SINGLE_QUOTES);
                    } else {
                        values.append(propertyValue);
                    }
                    values.append(COMMA);
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                LOGGER.error("拼装insert语句异常:" + ExceptionUtils.getStackTrace(e));
            }
        });
        if (StringUtils.isNoneBlank(columns.toString())) {
            sql = new StringBuffer(INSERT);
            sql.append(SPACE).append(tableName).append(SPACE).append(LEFT_BRACKET)
                    .append(columns.toString().substring(0, columns.length() - 1)).append(RIGHT_BRACKET).append(SPACE).append(VALUES).append(SPACE)
                    .append(LEFT_BRACKET).append(values.toString().substring(0, values.length() - 1)).append(RIGHT_BRACKET);
        }
        return sql == null ? null : sql.toString();
    }

    /**
     * 更新SQL
     *
     * @param obj    更新对象
     * @param id     主键
     * @param userId 用户ID
     * @return
     */
    public static String updateSQL(Object obj, String id, Long userId) {
        /* SQL */
        StringBuffer sql = null;
        StringBuffer sets = new StringBuffer();
        /* 得到类对象 */
        Class<? extends Object> objClass = obj.getClass();
        /* 获取表名 */
        String tableName = classNameToTableName(objClass.getSimpleName(), TABLE_PREFIX, SUFFIX);
        /* 得到类中所有属性集合 */
        Field[] fields = objClass.getDeclaredFields();
        Arrays.asList(fields).forEach(field -> {
            /* 设置此属性可访问 */
            field.setAccessible(true);
            /* 属性名 */
            String propertyName = field.getName();
            try {
                /* 属性值 */
                Object propertyValue = field.get(obj);
                if (propertyValue != null && StringUtils.isNoneBlank(propertyValue.toString()) && !propertyName.equals(ID) && !propertyName.equals(USERID)) {
                    sets.append(SPACE).append(javaPropertyToColumnName(propertyName)).append(SPACE).append(EQUAL_SIGN).append(SPACE);
                    if (field.getType() == String.class) {
                        sets.append(SINGLE_QUOTES).append(propertyValue).append(SINGLE_QUOTES);
                    } else {
                        sets.append(propertyValue);
                    }
                    sets.append(COMMA);
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                LOGGER.error("拼装update语句异常:" + ExceptionUtils.getStackTrace(e));
            }
        });
        if (StringUtils.isNoneBlank(sets.toString()) && StringUtils.isNotBlank(id) && userId != null && userId.longValue() > 0) {
            sql = new StringBuffer(UPDATE);
            sql.append(SPACE).append(tableName).append(SPACE).append(SET)
                    .append(sets.toString().substring(0, sets.length() - 1)).append(SPACE).append(WHERE).append(SPACE)
                    .append(ID).append(SPACE).append(EQUAL_SIGN).append(SPACE).append(SINGLE_QUOTES).append(id).append(SINGLE_QUOTES)
                    .append(SPACE).append(AND).append(SPACE).append(USER_ID).append(SPACE).append(EQUAL_SIGN).append(SPACE).append(userId);
        }
        return sql == null ? null : sql.toString();
    }

    /**
     * 拼装查询参数
     *
     * @param obj    查询对象
     * @param params 参数
     */
    public static void assembleQueryParameters(Object obj, Map<Object, Object> params) {
        if (obj != null) {
            /* 得到类对象 */
            Class<? extends Object> objClass = obj.getClass();
            /* 得到类中所有属性集合 */
            Field[] fields = objClass.getDeclaredFields();
            Arrays.asList(fields).forEach(field -> {
                /* 设置此属性可访问 */
                field.setAccessible(true);
                /* 属性名 */
                String propertyName = field.getName();
                try {
                    /* 属性值 */
                    Object propertyValue = field.get(obj);
                    if (propertyValue != null && StringUtils.isNoneBlank(propertyValue.toString())) {
                        if (FieldReflectionUtil.checkValueType(field, propertyValue)) {
                            if (FieldReflectionUtil.checkValueGreaterThanZero(field, propertyValue)) {
                                params.put(propertyName, propertyValue);
                            }
                        } else {
                            params.put(propertyName, propertyValue);
                        }
                    }
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    LOGGER.error("拼装查询参数异常:" + ExceptionUtils.getStackTrace(e));
                }
            });
            /* 统一设置删除标识 */
            //params.put("deleteFlag", CommonConstants.DeleteFlag.NOTDEL.getValue());
        }
    }


    /**
     * 拼装查询参数
     *
     * @param obj    查询对象
     * @param params 参数
     */
    public static void queryParameters(Object obj, Map<String, Object> params) {
        if (obj != null) {
            /* 得到类对象 */
            Class<? extends Object> objClass = obj.getClass();
            /* 得到类中所有属性集合 */
            Field[] fields = objClass.getDeclaredFields();
            Arrays.asList(fields).forEach(field -> {
                /* 设置此属性可访问 */
                field.setAccessible(true);
                /* 属性名 */
                String propertyName = field.getName();
                try {
                    /* 属性值 */
                    Object propertyValue = field.get(obj);
                    if (propertyValue != null && StringUtils.isNoneBlank(propertyValue.toString())) {
                        if (FieldReflectionUtil.checkValueType(field, propertyValue)) {
                            if (FieldReflectionUtil.checkValueGreaterThanZero(field, propertyValue)) {
                                params.put(propertyName, propertyValue);
                            }
                        } else {
                            params.put(propertyName, propertyValue);
                        }
                    }
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    LOGGER.error("拼装查询参数异常:" + ExceptionUtils.getStackTrace(e));
                }
            });
            /* 统一设置删除标识 */
            params.put("isDeleted", CommonConstants.IsDeleted.NOTDEL.getValue());
        }
    }

    /**
     * Java属性名转换成列名
     *
     * @param propertyName
     * @return
     */
    public static String javaPropertyToColumnName(String propertyName) {
        char[] chars = propertyName.toCharArray();
        StringBuffer sb = new StringBuffer();
        for (char c : chars) {
            if (CharUtils.isAsciiAlphaUpper(c)) {
                sb.append("_" + StringUtils.lowerCase(CharUtils.toString(c)));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * Java类名转换成表名
     *
     * @param className
     * @param tablePrefix
     * @param classSuffix
     * @return
     */
    public static String classNameToTableName(String className, String tablePrefix, String classSuffix) {
        String tableName = javaPropertyToColumnName(className.replace(classSuffix, ""));
        if (StringUtils.isNotBlank(tablePrefix)) {
            tableName = tablePrefix + tableName;
        }
        return tableName;
    }
}

